/**
 * @file My_Debug.h
 * @author 蔡云蔚 (you@domain.com)
 * @brief 蓝牙，型号：深圳市新一信息技术有限公司XY-MBD06A 模块
 * @version 0.1
 * @date 2024-10-09
 * 
 * @copyright Copyright (c) 2024
 * 
 */
#pragma once


#include "usart.h"
#include "my_redifine.h"

/**
 * @brief 串口调试类
 * 
 */
class My_Debug
{
//===========饿汉模式，只能实例化一个
private:
  static My_Debug only;//静态实例
public:
  /**
   * @brief Get the Instance object
   * 
   * @return My_Debug& 
   */
  static My_Debug& getInstance();
private:
  /**
   * @brief Construct a new My_Debug object
   * @note 私有化构造函数，防止外部直接创建实例
   */
  My_Debug(){};
private:
  /**
   * @brief Destroy the My_Debug object
   * @note 私有化析构函数 
   */
  ~My_Debug(){};
private:
  /**
   * @brief Construct a new My_Debug object
   * @note 禁用拷贝构造
   */
  My_Debug(const My_Debug&) = delete;
private:
  /**
   * @brief 赋值运算
   * @return My_Debug& 
   * @note 禁用掉
   */
  My_Debug& operator=(const My_Debug&) = delete;

public:
  /**
   * @brief 初始化
   * @note 涉及操作系统时请在线程中初始化
   */
  void init(void);

public:
  bool Transmitted = true;//串口发送完成标志

public:
  /**
   * @brief 通过串口发送
   * 
   * @param pData 发送数据的起始地址
   * @param Size 要发送的数据数量
   * @param Timeout 超时时间（毫秒）
   * @return HAL_StatusTypeDef 
   */
  HAL_StatusTypeDef transmit(const uint8_t* pData, uint16_t Size, uint32_t Timeout);

public:
  /**
   * @brief 通过串口发送中断
   * 
   * @param pData 发送数据的起始地址
   * @param Size 要发送的数据数量
   * @return HAL_StatusTypeDef 
   * @note 配合HAL_UART_TxCpltCallback
   */
  HAL_StatusTypeDef transmit_IT(const uint8_t* pData, uint16_t Size);

public:
  /**
   * @brief 设置一次DMA串口发送
   * 
   * @param pData 发送数据的位置
   * @param Size 要发送的数据数量
   * @return HAL_StatusTypeDef
   * @note 配合HAL_UART_TxCpltCallback
   * @note 已加锁
   */
  HAL_StatusTypeDef transmit_DMA(const uint8_t* pData, uint16_t Size);

public:
  /**
   * @brief 接收完成标志 
   * @note 接收完成后为 true
   */
  bool Received = false;
  /**
   * @brief 从串口接收到的数据缓冲区
   * @note 在DMA模式下直接由DMA写，无法加锁
   */
  uint8_t ReBuffer[256] = {0x00};
  /**
   * @brief 串口接收到的数据数量
   * @note 在DMA模式下直接由DMA写，无法加锁
   */
  uint16_t ReCount = 0;

public:
  /**
   * @brief 通过串口接收一定长度的数据
   * 
   * @param Size 数据长度
   * @param Timeout 超时时间
   * @return HAL_StatusTypeDef 
   * @note 接收到的数据保存至ReBuffer
   * @note 直接设置接收到的数量ReCount
   */
  HAL_StatusTypeDef receive(uint16_t Size, uint32_t Timeout);

public:
  /**
   * @brief 通过串口中断接收一定长度的数据
   * 
   * @param Size 数据长度
   * @return HAL_StatusTypeDef 
   * @note 接收到的数据保存至ReBuffer
   * @note 直接设置接收到的数量ReCount
   * @note 配合HAL_UART_RxCpltCallback
   */
  HAL_StatusTypeDef receive_IT(uint16_t Size);

public:
  /**
   * @brief 通过串口接收到空闲
   * 
   * @param Timeout 超时时间（毫秒）
   * @return HAL_StatusTypeDef
   * @note 接收到的数据保存至ReBuffer
   * @note 接收到的数量保存至ReCount
   */
  HAL_StatusTypeDef receiveToIdle(uint32_t Timeout);

public:   
  /**
   * @brief 设置一次DMA串口接收到空闲
   * 
   * @return HAL_StatusTypeDef 
   * 
   * @note 接收完成后
   * @note 接收到的数据保存至ReBuffer
   * @note 接收到的数量保存至ReCount
   * @note 配合HAL_UART_RxCpltCallback
   */
  HAL_StatusTypeDef receiveToIdle_DMA();

};

extern My_Debug& my_debug;//实例化的调试串口引用

/**
 * @brief 调试模式枚举
 * @note 强类型枚举
 */
enum class Debug_Mode : uint8_t
{
  normal = 0,
  imu = 1,
  bluetooth = 2
};

extern Debug_Mode debug_mode;//调试模式


















